import os
import pickle
import random
import time
import tkinter
import tkinter.messagebox
import pyaudio
import wave
from pydub.playback import play

# 面试类
from pydub import AudioSegment


class Interview:
    question_label = True;
    answer_label = True;
    exit_status = False;
    # 存储问题及答案的map
    qus_ans_dict = {};
    # 存储播放问题顺序的list
    qus_list = []

    # 序列化内存数据到本地
    def record_result(self):
        result = {};
        result['qus_ans_dict'] = self.qus_ans_dict;
        result['qus_list'] = self.qus_list;
        writeWord(result)
        return result;

    # 序列化本地数据到内存
    def read_result(self):
        result = readWord();
        self.qus_list = result['qus_list'];
        self.qus_ans_dict = result['qus_ans_dict'];
        return result;

    # 负责问题录音
    def question_rec(self, file_name, tk):
        self.question_label = True;
        CHUNK = 1024
        FORMAT = pyaudio.paInt16
        CHANNELS = 2
        RATE = 16000
        RECORD_SECONDS = 2
        p = pyaudio.PyAudio()
        stream = p.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=True,
                        frames_per_buffer=CHUNK)
        frames = []
        print('请说话')
        a = tkinter.messagebox.askquestion(title='录音启动信息', message='请讲话！')
        if a == 'no':
            return;
        while self.question_label == True:
            data = stream.read(CHUNK)
            frames.append(data)
        # 将问题添加到问题列表中并序列化到本地
        if file_name not in self.qus_list:
            self.qus_list.append(file_name);
        self.record_result();
        stream.stop_stream()
        stream.close()
        p.terminate()
        wf = wave.open(f'ques_answer_audio/{file_name}', 'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
        wf.close()
        tkinter.messagebox.showinfo(title='Hi', message='录音已结束！')
        print('录音已结束')

    # 负责终止/启动问题录音
    def update_question_label(self, label):
        self.question_label = label;

    def hand_start(self):
        tkinter.messagebox.showinfo(title='模拟面试', message='面试已开始,点击是开始参加！')
        try:
            self.read_result()
        except:
            tkinter.messagebox.showinfo(title='Hi', message='当前没有任何问题列表,请添加问题后再开始面试')
            return;
        repeat = set([]);
        while len(repeat) != len(self.qus_list) and self.exit_status == False:
            item = random.choice(self.qus_list)
            if item not in repeat:
                playsound(item);
                repeat.add(item)
                # time.sleep(5)
                answer_audio = f'{item}回答.wav';
                # 开始录音记录回答
                self.answer_rec(item, answer_audio)
                # 之后保存答案到内存及序列化到本地
                self.qus_ans_dict[item] = answer_audio;
                self.record_result();
        tkinter.messagebox.showinfo(title='Hi', message='面试已结束')

    # 负责回答录音
    def answer_rec(self, qus_name, ans_name):
        self.answer_label = True;
        CHUNK = 1024
        FORMAT = pyaudio.paInt16
        CHANNELS = 2
        RATE = 16000
        RECORD_SECONDS = 2
        p = pyaudio.PyAudio()
        stream = p.open(format=FORMAT,
                        channels=CHANNELS,
                        rate=RATE,
                        input=True,
                        frames_per_buffer=CHUNK)
        frames = []
        print('请讲话,点击下一题结束此问题的回答')
        while self.answer_label == True:
            data = stream.read(CHUNK)
            frames.append(data)
        print('请闭嘴')
        # 将答案以及问题装到map中并序列化到本地
        self.qus_ans_dict[qus_name] = ans_name;
        self.record_result();
        # 流式保存回答录音
        stream.stop_stream()
        stream.close()
        p.terminate()
        wf = wave.open(f'ques_answer_audio/{ans_name}', 'wb')
        wf.setnchannels(CHANNELS)
        wf.setsampwidth(p.get_sample_size(FORMAT))
        wf.setframerate(RATE)
        wf.writeframes(b''.join(frames))
        wf.close()

    # 负责终止/启动回答录音
    def update_answer_label(self, label):
        self.answer_label = label;

    # 负责终止/启动回答录音
    def update_exit_label(self, label):
        self.exit_status = True;
        self.answer_label = label;


    # 根据问题,播放对应录音
    def play_qus_answer_audio(self, question):
        if question not in self.qus_ans_dict:
            tkinter.messagebox.showinfo(title='查看结果', message='当前问题无对应的回答信息！')
            playsound(question)
            return
        # 播放对应的问答
        playsound(question)
        playsound(self.qus_ans_dict.get(question))

    # 　删除数据并序列化到本地
    def del_qus_ans_audio(self, item, lb):
        lb.delete(lb.curselection())
        self.qus_list.remove(item);
        os.remove(f'ques_answer_audio/{item}')
        if item in self.qus_ans_dict:
            os.remove(f'ques_answer_audio/{self.qus_ans_dict[item]}')
            del self.qus_ans_dict[item]
        self.record_result()


# 播放音频工具类
def playsound(audio):
    audio = f'ques_answer_audio/{audio}'
    song = AudioSegment.from_wav(audio)
    play(song)


# 序列化工具类
def writeWord(data):
    f = open("data.txt", "wb")
    pickle.dump(data, f, True);
    f.close()

    # 读URL


# 序列化工具类
def readWord():
    f = open("data.txt", "rb")
    data = pickle.load(f)
    f.close()
    return data;


if __name__ == '__main__':
    interview = Interview()
    # interview.play_music('你上家公司离职的原因.wav')
    interview.play_music('开始吧.wav')
